package edu.mse.camel.client.posterboard.ui.editpart;

import java.util.List;

import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.FreeformLayer;
import org.eclipse.draw2d.FreeformLayout;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.MarginBorder;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartFactory;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
import org.eclipse.gef.editpolicies.RootComponentEditPolicy;
import org.eclipse.gef.ui.palette.PaletteViewer;
import org.eclipse.jface.viewers.StructuredSelection;

import edu.mse.camel.client.posterboard.posterboard.PBDiagram;
import edu.mse.camel.client.posterboard.posterboard.Posterboard;
import edu.mse.camel.client.posterboard.ui.editor.PosterBoardEditorPaletteFactory;
import edu.mse.camel.client.posterboard.ui.editor.PosterBoardModelManager;
import edu.mse.camel.client.posterboard.ui.editpart.policy.PosterBoardXYLayoutEditPolicy;

public class PosterBoardEditpart extends AbstractGraphicalEditPart
									implements Adapter {

	private PosterBoardModelManager pbModelManager;
	
	public PosterBoardEditpart(Posterboard pb, PosterBoardModelManager pbModelManager) {
		super();
		setModel(pb);
		this.pbModelManager = pbModelManager;
	}

	@Override
	protected IFigure createFigure() {
		Figure f = new FreeformLayer();
		f.setBorder(new MarginBorder(3));
		f.setLayoutManager(new FreeformLayout());
		return f;
	}

	@Override
	protected void createEditPolicies() {
		// disallows the removal of this edit part from its parent
		installEditPolicy(EditPolicy.COMPONENT_ROLE, new RootComponentEditPolicy());
		// handles constraint changes (e.g. moving and/or resizing) of model elements
		// and creation of new model elements
		installEditPolicy(EditPolicy.LAYOUT_ROLE,  
				new PosterBoardXYLayoutEditPolicy(pbModelManager));
	}

	@Override
	public Notifier getTarget() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean isAdapterForType(Object type) {
		return this.getModel().getClass().equals(type.getClass());
	}

	@Override
	public void notifyChanged(Notification notification) {
		int type = notification.getEventType();
		switch( type ) {
			case Notification.ADD:
				Object newValue = notification.getNewValue();
				if (newValue instanceof PBDiagram) {
					EditPart newPart = 
						getViewer().getEditPartFactory().createEditPart(this, newValue);
					addChild(newPart, 0);
					getViewer().setSelection(new StructuredSelection(newPart));
				}
				break;
			case Notification.ADD_MANY:
			case Notification.REMOVE:
			case Notification.REMOVE_MANY:
				refresh();
				break;
			case Notification.SET:
				refreshVisuals();
				break;
		}
	}

	@Override
	public void setTarget(Notifier newTarget) {
		// TODO Auto-generated method stub
		
	}

	@Override
	protected List getModelChildren() {
		return getPosterBoard().getDiagrams();
	}
	
	protected Posterboard getPosterBoard() {
		return (Posterboard) getModel();
	}

	@Override
	public void activate() {
		if (isActive()) {
			return;
		}
		getPosterBoard().eAdapters().add(this);
		super.activate();
	}
	
	@Override
	public void deactivate() {
		if (!isActive()) {
			return;
		}
		getPosterBoard().eAdapters().remove(this);
		super.deactivate();
	}

	public void diagramSelectionChanged(
			GraphicalEditPart diagramEditpart, String diagramType) {
		changeZOrder(diagramEditpart);
		changePalette(diagramType);
		changeEditPartFactoryDelegate(diagramType);
	}

	private void changeZOrder(
			GraphicalEditPart diagramEditpart) {
		if (this.children != null) {
			this.children.remove(diagramEditpart);
			this.children.add(diagramEditpart);
		}
		
		if (this.figure.getChildren() != null) {
			this.figure.getChildren().remove(diagramEditpart.getFigure());
			this.figure.getChildren().add(diagramEditpart.getFigure());
		}
		this.figure.repaint();
	}

	private void changePalette(String diagramType) {
		final PaletteViewer paletteViewer = getViewer().getEditDomain().getPaletteViewer();
		// best solution for now is to remove all existing palette entries
		removeAllPaletteEntries(paletteViewer);
		paletteViewer.getPaletteRoot().add(
				PosterBoardEditorPaletteFactory.palettes.get(diagramType));
	}
	
	private void removeAllPaletteEntries(PaletteViewer paletteViewer) {
		for (String type : PosterBoardEditorPaletteFactory.palettes.keySet()) {
			paletteViewer.getPaletteRoot().remove(
					PosterBoardEditorPaletteFactory.palettes.get(type));
		}
	}

	private void changeEditPartFactoryDelegate(String diagramType) {
		EditPartFactory factory  = getViewer().getEditPartFactory();
		if (factory instanceof PosterBoardEditPartFactory) {
			PosterBoardEditPartFactory pFactory = (PosterBoardEditPartFactory) factory;
			pFactory.setAdapter(diagramType);
		}
	}
	
}
